#include "irm_datamodel.h"
#include "json/reader.h"
#include "json/json.h"
#include <QDebug>
#include <iostream>

namespace ophies {


RequestCallback::RequestCallback(DataModelType type, QObject *parent) :
    QObject(parent),
    m_callback_type(type)

{

}

RequestCallback::~RequestCallback()
{
    qDebug() << "request callback deleted. type: " ;
}

void RequestCallback::onAuthenticationRequired(QNetworkReply*, QAuthenticator*)
{
    std::cout << "RequestCallback::onAuthenticationRequired called" << std::endl;
}

void RequestCallback::onFinished(QNetworkReply *r)
{
    //    std::cout << r->readAll();
    //    std::cout << "RequestCallback::onFinished called 11";
    qDebug() << "RequestCallback::onFinished called" ;
    handlResponse(r);
    r->deleteLater();
}

void RequestCallback::myListHandler(QList<DataModel*>* list)
{
	if(list) 
		std::cout << "object is not null but ... " << std::endl;

    std::cout << "onListReceived is not implemented" << " class type: " << m_callback_type << std::endl;
}

void RequestCallback::myObjectHandler(DataModel* object)
{
	if(object)
		std::cout << "object is not null but ... " << std::endl;

    std::cout << "onObjectReceived is not implemented" << " class type: " << m_callback_type << std::endl;
}

void RequestCallback::handlResponse( QNetworkReply *r )
{
    qDebug() << "handle response: ";
    QList<DataModel*> *list = new QList<DataModel*>();

    Json::Value *root_shadow = new Json::Value;
    Json::Value root = &(*root_shadow);
    Json::Reader reader;
    Json::Value *temp;

    QString jsonStr = QString(r->readAll());

    qDebug() << "JSON String size: " << jsonStr.size() <<
                "type: " << (int)m_callback_type;

    bool result = reader.parse(jsonStr.toStdString(), root);
    if(!result)
    {
    //         report to the user the failure and their locations in the document.
        qDebug() << "cound not parse the reply";
        std::cout  << "Failed to parse configuration\n"
                   << reader.getFormattedErrorMessages().c_str() << std::endl;
    }

    if(root.isArray()) // json array
	{
        qDebug() << "json is array. count: " << root.size();
        switch(m_callback_type)
        {
            case DCM_STUDY:
                for(unsigned int i = 0; i < root.size(); i++)
                {
                    temp = &root[i];
                    DcmStudy *p = new DcmStudy(parent()); // fixme
                    p->fromJson(*temp);
                    *list << (p);
                }
                break;
            case DCM_SERIES:
                for(unsigned int i = 0; i < root.size(); i++)
                {
                    temp = &root[i];
                    DcmSeries *p = new DcmSeries(parent()); // fixme
                    p->fromJson(*temp);
                    *list << (p);
                }
                break;
            case DCM_INSTANCE:
                for(unsigned int i = 0; i < root.size(); i++)
                {
                    temp = &root[i];
                    DcmInstance *p = new DcmInstance(parent()); // fixme
                    p->fromJson(*temp);
                    *list << (p);
                }
                break;
            case DOCSET:
                for(unsigned int i = 0; i < root.size(); i++)
                {
                    temp = &root[i];
                    Docset *p = new Docset(parent()); // fixme
                    p->fromJson(*temp);
                    *list << (p);
                }
                break;
            case PATIENT:
                for(unsigned int i = 0; i < root.size(); i++)
                {
                    temp = &root[i];
                    Patient *p = new Patient(parent()); // fixme
                    p->fromJson(*temp);
                    *list << (p);
                }
                break;
            default:
                for(unsigned int i = 0; i < root.size(); i++)
                {
                    temp = &root[i];
                    DataModel *p = new DataModel(UNKNOWN, parent()); // fixme
                    p->fromJson(*temp);
                    *list << (p);
                }
                break;
        }

        myListHandler(list);

    } else if(root.isObject()) // json object
	{
        qDebug() << "json is object. ";
        DataModel* d;

        switch(m_callback_type)
        {
        case DCM_STUDY:
            d = new DcmStudy(parent());
            break;
        case DCM_SERIES:
            d = new DcmSeries(parent());
            break;
        case DCM_INSTANCE:
            d = new DcmInstance(parent());
            break;
        case DOCSET:
            d = new Docset(parent());
            break;
        case PATIENT:
            d = new Patient(parent());
            break;
        default:
            d = new DataModel(UNKNOWN, parent());
            break;
        }

        d->fromJson(root);
        myObjectHandler(d);

	} else {
        qDebug() << "xxxx";
	}


}




/////////////////////////////////////////////////////////////////
/// \brief PatientsCallback::PatientsCallback
/// \param parent
////////////////////////////////////////////////////////////////
PatientsCallback::PatientsCallback(QObject *parent) :
    RequestCallback(ophies::PATIENT, parent)
{

}

PatientsCallback::~PatientsCallback()
{

}





/////////////////////////////////////////////////////////////////
/// \brief DcmStudiesCallback::DcmStudiesCallback
/// \param parent
/////////////////////////////////////////////////////////////////
DcmStudiesCallback::DcmStudiesCallback(QObject *parent) :
    RequestCallback(ophies::DCM_STUDY, parent)
{
}

DcmStudiesCallback::~DcmStudiesCallback()
{

}



////////////////////////////////////////////////////////////////
/// \brief DcmSeriesCallback::DcmSeriesCallback
/// \param parent
///////////////////////////////////////////////////////////////
DcmSeriesCallback::DcmSeriesCallback(QObject *parent) :
    RequestCallback(ophies::DCM_SERIES, parent)
{
}

DcmSeriesCallback::~DcmSeriesCallback()
{

}





//////////////////////////////////////////////////////////////
/// \brief DcmInstancesCallback::DcmInstancesCallback
/// \param parent
//////////////////////////////////////////////////////////////
DcmInstancesCallback::DcmInstancesCallback(QObject *parent) :
    RequestCallback(ophies::DCM_INSTANCE, parent)
{
}

DcmInstancesCallback::~DcmInstancesCallback()
{

}





//////////////////////////////////////////////////////////////
/// \brief DocsetCallback::DocsetCallback
/// \param parent
//////////////////////////////////////////////////////////////
DocsetsCallback::DocsetsCallback(QObject *parent) :
    RequestCallback(ophies::DOCSET, parent)
{
}

DocsetsCallback::~DocsetsCallback()
{

}

} // namespace ophies


